package com.boot.producer.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.boot.producer.entity.BasicInfo;
import com.boot.producer.entity.Violation;
import com.boot.producer.service.BasicInfoService;
import com.boot.producer.service.GradeService;
import com.boot.producer.service.ViolationService;
import com.boot.producer.service.dto.GradeDto;
import com.boot.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* FileName: GradeServiceImpl.java
* 评分服务实现类
*
* @author 张志磊
* @date   2019/3/1 14:58
* @version 1.0
*/
@Service
public class GradeServiceImpl implements GradeService {
    @Autowired
    BasicInfoService basicInfoService;
    @Autowired
    ViolationService violationService;
    @Override
    public GradeDto getGradeByDate(Date date) {
        double a[][] = {{1, 1, 2, 3, 1.0/2},
                        {1, 1, 2, 3, 1.0/2},
                        {1.0/2, 1.0/2, 1, 2, 1.0/4},
                        {1.0/3, 1.0/3, 1.0/2, 1, 1.0/5},
                        {2, 2, 4, 5, 1}};
        double b[][] = {{1, 1.0/4},
                        {4,1}};
        double c[][] = {{1, 1.0/2},
                        {2, 1}};
        double d[][] = {{1, 3},
                        {1.0/3, 1}};
        double e[][] = {{1,1.0/5},
                        {5,1}};
        double f[][] = {{1, 2, 1.0/3, 1.0/2},
                        {1.0/2, 1, 1.0/3, 1.0/2},
                        {3, 3, 1, 2},
                        {2, 2, 1.0/2, 1}};
        List<double[]> weightList = new ArrayList<>();
//        二级指标权重
        weightList.add(getWeight(a, 5));
//        行驶车速
        weightList.add(getWeight(b, 2));
//        每日出行
        weightList.add(getWeight(c, 2));
//        疲劳驾驶
        weightList.add(getWeight(d, 2));
//        夜间行驶
        weightList.add(getWeight(e, 2));
//        四急驾驶
        weightList.add(getWeight(f, 4));
        GradeDto gradeDto = new GradeDto();

        List<Double> scores = new ArrayList<>();
        gradeDto.setScores(scores);
        BasicInfo basicInfo = basicInfoService.selectOne(new EntityWrapper<BasicInfo>().eq("time", date));
//        List<Violation> violationList = violationService.selectList(new EntityWrapper<Violation>().eq("date", date));
//        for (Violation violation:violationList) {
//
//        }
        if (basicInfo == null){
            GradeDto gradeDto1 = new GradeDto();
            List<Double> scs = new ArrayList<>();
            scs.add(100d);
            scs.add(100d);
            scs.add(100d);
            scs.add(100d);
            scs.add(100d);
            gradeDto1.setScores(scs);
            gradeDto1.setSynthesizeScore(100);
             return gradeDto1;
        }
        Map<Integer, Integer> timesMap = violationService.listTimesByDate(date);
        //求出每项数据分数
        //分数加权
        List<double[]> firstGrade = new ArrayList<>();
        double[] speed = new double[2];
        speed[0] = avgSpeed(basicInfo.getAvgSpeed());
        speed[1] = overSpeed(timesMap.get(1));
        //行驶车速
        scores.add(speed[0]*weightList.get(1)[0]+speed[1]*weightList.get(1)[1]);
        double[] daily = new double[2];
        daily[0] = totalTime(basicInfo.getTotalTime());
        daily[1] = totalDistance(basicInfo.getTotalDistance());
        scores.add(daily[0]*weightList.get(2)[0]+daily[1]*weightList.get(2)[1]);
        double tireds[] = new double[2];
        tireds[0] = contineTime((double)basicInfo.getContinueTime());
        tireds[1] = tired(timesMap.get(6));
        scores.add(tireds[0]*weightList.get(3)[0]+tireds[1]*weightList.get(3)[1]);

        double nights[] = new double[2];
        nights[0] = nightSpeed(basicInfo.getNightSpeed());
        nights[1] = nightTime(basicInfo.getNightTime());
        scores.add(nights[0]*weightList.get(4)[0]+nights[1]*weightList.get(4)[1]);

        double hurry[] = new double[4];
        hurry[0] = threeV(timesMap.get(2));
        hurry[1] = threeV(timesMap.get(3));
        hurry[2] = oneV(timesMap.get(4));
        hurry[3] = threeV(timesMap.get(5));
        scores.add(hurry[0]*weightList.get(5)[0]+hurry[1]*weightList.get(5)[1]+hurry[2]*weightList.get(5)[2]+hurry[3]*weightList.get(5)[3]);

        gradeDto.setSynthesizeScore(scores.get(0)*weightList.get(0)[0]+scores.get(1)*weightList.get(0)[1]+scores.get(2)*weightList.get(0)[2]+scores.get(3)*weightList.get(0)[3]+scores.get(4)*weightList.get(0)[4]);


        return gradeDto;
    }

    @Override
    public List<GradeDto> listOneWeek(Date begin,Date end) {
        List<GradeDto> gradeDtos = new ArrayList<>();
        for (int i = 0; i < DateUtil.differentDays(begin,end)+1; i++) {
           gradeDtos.add( getGradeByDate(DateUtil.changeDay(end,-i)));
        }
        return gradeDtos;
    }

    //    平均车速
    private int avgSpeed(double speed){
//        if (speed == null){
//            return 100;
//        }
        if (speed < 35 ){
            return 100;
        } else if (speed <50){
            return 90;
        } else if (speed < 60) {
            return 75;
        } else if (speed < 80){
            return 50;
        } else {
            return 20;
        }
    }
//    超速次数
    private int overSpeed(int time){
        if (time == 0){
            return 100;
        }
        if (time == 1|| time == 2){
            return 85;
        } else if (time == 3|| time == 6){
            return 70;
        } else if(time == 1|| time == 2) {
            return 50;
        } else{
            return 10;
        }
    }
//    总里程
    private int totalDistance(double distance){
        if (distance<=30){
            return 100;
        } else if (distance <= 40){
            return 90;
        } else if (distance <= 70){
            return 80;
        } else if (distance <= 90){
            return 60;
        } else if (distance<=120){
            return 50;
        } else if (distance <= 200){
            return 30;
        } else {
            return 10;
        }
    }

//    驾驶时长
    private int totalTime(double time){
        if (time <= 120){
            return 100;
        } else if (time <= 180){
            return 85;
        } else if (time <= 240){
            return 70;
        } else if (time <= 360) {
            return 50;
        } else if (time<= 420) {
            return 25;
        } else {
            return 10;
         }
    }
//    连续时间
    private int contineTime(Double time){
        if (time <= 120){
            return 100;
        } else if (time <= 180){
            return 80;
        } else if (time <= 240){
            return 70;
        } else if (time <= 360) {
            return 50;
        } else {
            return 10;
        }
    }
//    疲劳驾驶次数
    private int tired(int time){
        if (time == 0){
            return 100;
        }
        if (time == 1){
            return 80;
        } else if (time == 2){
            return 50;
        } else {
            return 10;
        }
    }
//    夜间行驶时间
    private int nightTime(double time){
        if (time <=60){
            return 100;
        } else if (time<= 120){
            return 85;
        } else if (time <= 180){
            return 60;
        } else if (time <= 300){
            return 40;
        } else {
            return 10;
        }
    }
//    夜间行驶车速
    private int nightSpeed(double speed){
        if (speed< 30){
            return 100;
        } else if (speed < 40){
            return 90;
        } else if (speed <50){
            return 75;
        } else if (speed <60){
            return 50;
        } else {
            return 10;
        }
    }
    //三个四急
    private int threeV(int time){
        if (time ==0){
            return 100;
        } else if (time== 1){
            return 95;
        } else if (time == 2 || time == 3){
            return 85;
        } else if (time == 4 || time == 5){
            return 65;
        } else if (time >= 6 && time <=9){
            return 40;
        } else {
            return 20;
        }
    }
//    一个四急
    private int oneV(int time){
        if (time ==0){
            return 100;
        } else if (time== 1){
            return 85;
        } else if (time == 2 ){
            return 70;
        } else if (time == 4 || time == 3){
            return 50;
        } else {
            return 20;
        }
    }

    private double[] getWeight(double[][] a, int count){
        double a1[] = new double[count];
        double a2[] = new double[count];
        double a3[] = new double[count];
        for (int i = 0;i<count;i++){
            double t = 1;
            for (int j = 0; j < count; j++) {
                t = t * a[i][j];
            }
            a1[i] = t;
        }
        double sum = 0;
        for (int i = 0; i < count; i++) {
            a2[i] = Math.pow(a1[i], 1.0/count);
            sum += a2[i];
        }
        for (int i = 0; i < count; i++) {
            a3[i] = a2[i]/sum;
        }
        return a3;
    }
}
